package com.yzy.fly.boot;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
public class WebServerDetector {

    public static final String GERONIMO_ID = "geronimo";

    public static final String GLASSFISH_ID = "glassfish";

    public static final String JBOSS_ID = "jboss";

    public static final String JETTY_ID = "jetty";

    public static final String JONAS_ID = "jonas";

    public static final String OC4J_ID = "oc4j";

    public static final String RESIN_ID = "resin";

    public static final String TOMCAT_ID = "tomcat";

    public static final String WEBLOGIC_ID = "weblogic";

    public static final String WEBSPHERE_ID = "websphere";

    public static String getServerName() {
        String serverName = null;
        if (WebServerDetector.isWebLogic()) {
            serverName = "WebLogic";
        } else if (WebServerDetector.isTomcat()) {
            serverName = "Tomcat";
        } else if (WebServerDetector.isWebSphere()) {
            serverName = "WebSphere";
        } else if (WebServerDetector.isSupportsComet()) {
            serverName = "SupportsComet";
        } else if (WebServerDetector.isResin()) {
            serverName = "Resin";
        } else if (WebServerDetector.isOC4J()) {
            serverName = "OC4J";
        } else if (WebServerDetector.isJOnAS()) {
            serverName = "JOnAS";
        } else if (WebServerDetector.isJetty()) {
            serverName = "Jetty";
        } else if (WebServerDetector.isJBoss()) {
            serverName = "JBoss";
        } else if (WebServerDetector.isGeronimo()) {
            serverName = "Geronimo";
        } else if (WebServerDetector.isGlassfish()) {
            serverName = "Glassfish";
        } else if (WebServerDetector.isGlassfish2()) {
            serverName = "Glassfish2";
        } else if (WebServerDetector.isGlassfish3()) {
            serverName = "Glassfish3";
        }
        return serverName;
    }

    public static String getServerId() {
        WebServerDetector sd = _instance;

        if (sd._serverId == null) {
            if (isGeronimo()) {
                sd._serverId = GERONIMO_ID;
            } else if (isGlassfish()) {
                sd._serverId = GLASSFISH_ID;
            } else if (isJBoss()) {
                sd._serverId = JBOSS_ID;
            } else if (isJOnAS()) {
                sd._serverId = JONAS_ID;
            } else if (isOC4J()) {
                sd._serverId = OC4J_ID;
            } else if (isResin()) {
                sd._serverId = RESIN_ID;
            } else if (isWebLogic()) {
                sd._serverId = WEBLOGIC_ID;
            } else if (isWebSphere()) {
                sd._serverId = WEBSPHERE_ID;
            }

            if (isJetty()) {
                if (sd._serverId == null) {
                    sd._serverId = JETTY_ID;
                } else {
                    sd._serverId += "-" + JETTY_ID;
                }
            } else if (isTomcat()) {
                if (sd._serverId == null) {
                    sd._serverId = TOMCAT_ID;
                } else {
                    sd._serverId += "-" + TOMCAT_ID;
                }
            }

            if (log.isInfoEnabled()) {
                if (sd._serverId != null) {
                    log.info("Detected server " + sd._serverId);
                } else {
                    log.info("No server detected");
                }
            }

            if (sd._serverId == null) {
                throw new RuntimeException("Server is not supported");
            }
        }

        return sd._serverId;
    }

    public static boolean isGeronimo() {
        WebServerDetector sd = _instance;

        if (sd._geronimo == null) {
            sd._geronimo = _detect(
                    "/org/apache/geronimo/system/main/Daemon.class");
        }

        return sd._geronimo.booleanValue();
    }

    public static boolean isGlassfish() {
        WebServerDetector sd = _instance;

        if (sd._glassfish == null) {
            String value = System.getProperty("com.sun.aas.instanceRoot");

            if (value != null) {
                sd._glassfish = Boolean.TRUE;
            } else {
                sd._glassfish = Boolean.FALSE;
            }
        }

        return sd._glassfish.booleanValue();
    }

    public static boolean isGlassfish2() {
        WebServerDetector sd = _instance;

        if (sd._glassfish2 == null) {
            if (isGlassfish() && !isGlassfish3()) {
                sd._glassfish2 = Boolean.TRUE;
            } else {
                sd._glassfish2 = Boolean.FALSE;
            }
        }

        return sd._glassfish2.booleanValue();
    }

    public static boolean isGlassfish3() {
        WebServerDetector sd = _instance;

        if (sd._glassfish3 == null) {
            String value = "";

            if (isGlassfish()) {
                value = getString(
                        System.getProperty("product.name"));
            }

            if (value.equals("GlassFish/v3")) {
                sd._glassfish3 = Boolean.TRUE;
            } else {
                sd._glassfish3 = Boolean.FALSE;
            }
        }

        return sd._glassfish3.booleanValue();
    }

    public static boolean isJBoss() {
        WebServerDetector sd = _instance;

        if (sd._jBoss == null) {
            sd._jBoss = _detect("/org/jboss/Main.class");
        }

        return sd._jBoss.booleanValue();
    }

    public static boolean isJetty() {
        WebServerDetector sd = _instance;

        if (sd._jetty == null) {
            sd._jetty = _detect("/org/mortbay/jetty/Server.class");
        }

        return sd._jetty.booleanValue();
    }

    public static boolean isJOnAS() {
        WebServerDetector sd = _instance;

        if (sd._jonas == null) {
            sd._jonas = _detect("/org/objectweb/jonas/server/Server.class");
        }

        return sd._jonas.booleanValue();
    }

    public static boolean isOC4J() {
        WebServerDetector sd = _instance;

        if (sd._oc4j == null) {
            sd._oc4j = _detect("oracle.oc4j.util.ClassUtils");
        }

        return sd._oc4j.booleanValue();
    }

    public static boolean isResin() {
        WebServerDetector sd = _instance;

        if (sd._resin == null) {
            sd._resin = _detect("/com/caucho/server/resin/Resin.class");
        }

        return sd._resin.booleanValue();
    }

    public static boolean isSupportsComet() {
        return false;
    }

    public static boolean isTomcat() {
        WebServerDetector sd = _instance;

        if (sd._tomcat == null) {
            sd._tomcat = _detect(
                    "/org/apache/catalina/startup/Bootstrap.class");
        }

        if (sd._tomcat == null) {
            sd._tomcat = _detect("/org/apache/catalina/startup/Embedded.class");
        }

        return sd._tomcat.booleanValue();
    }

    public static boolean isWebLogic() {
        WebServerDetector sd = _instance;

        if (sd._webLogic == null) {
            sd._webLogic = _detect("/weblogic/Server.class");
        }

        return sd._webLogic.booleanValue();
    }

    public static boolean isWebSphere() {
        WebServerDetector sd = _instance;

        if (sd._webSphere == null) {
            sd._webSphere = _detect(
                    "/com/ibm/websphere/product/VersionInfo.class");
        }

        return sd._webSphere.booleanValue();
    }

    private static Boolean _detect(String className) {
        try {
            ClassLoader.getSystemClassLoader().loadClass(className);

            return Boolean.TRUE;
        } catch (ClassNotFoundException cnfe) {
            WebServerDetector sd = _instance;

            Class<?> c = sd.getClass();

            if (c.getResource(className) != null) {
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        }
    }

    public static String getString(String value) {
        return getString(value, "");
    }

    public static String getString(String value, String defaultValue) {
        if (value != null) {
            value = value.trim();
            value = StringUtils.replace(
                    value, RETURN_NEW_LINE, NEW_LINE);
            return value;
        }
        return defaultValue;
    }

    private static WebServerDetector _instance = new WebServerDetector();
    public static final String RETURN_NEW_LINE = "\r\n";
    public static final String NEW_LINE = "\n";

    private String _serverId;
    private Boolean _geronimo;
    private Boolean _glassfish;
    private Boolean _glassfish2;
    private Boolean _glassfish3;
    private Boolean _jBoss;
    private Boolean _jetty;
    private Boolean _jonas;
    private Boolean _oc4j;
    private Boolean _resin;
    private Boolean _tomcat;
    private Boolean _webLogic;
    private Boolean _webSphere;

}
